import os
from ctypes import cdll, byref, create_string_buffer
import logging
import logging.handlers

LOG_LEVELS = {'debug': logging.DEBUG,
			'info': logging.INFO,
			'warning': logging.WARNING,
			'error': logging.ERROR,
			'critical': logging.CRITICAL
			}  

logger = None
def log( msg, level='error' ):
	"""
	A simplifyed log function. Simply supply a message and
	a log level. 


	=========  ===========================================================
	Parameter  
	=========  ===========================================================
	*msg*      Message string to be logged.
	*level*    Log level to use for this message. 
	=========  ===========================================================

	The log level is optional and defaults to 'error'. Log levels
	are given as a simple string. The available log levels are:

		* debug
		* info
		* warning
		* error
		* critical

	Where debug is the most verbose log level and critical is the least
	verbose log level.

	"""

	if level in LOG_LEVELS:
		log_lev = LOG_LEVELS[ level ]
	else:
		log_lev = logging.ERROR 

	global logger
	if not logger:
		logger = logging.getLogger( "dmq_service" )

	logger.log( log_lev, msg )     
#log()

def setLogLevel(log_level_str):
	"""set the process wide log level from a log level string
	
	===============  ===========================================================
	Parameter  
	===============  ===========================================================
	*log_level_str*  The log level to set the logger to 
	===============  ===========================================================

	"""
	log( "Setting log level to %s" % log_level_str, 'info' )
	#print( "Setting log level to %s" % log_level_str )

	log_lev =LOG_LEVELS['error']
	log_level_str = log_level_str.lower()
	if log_level_str in LOG_LEVELS:
		log_lev = LOG_LEVELS[ log_level_str ]

	logger.setLevel( log_lev )
#setLogLevel()

def start_logger( log_dir='/var/logs',
		log_file='dmq.log',
		log_level='error', service_type='zmq' ):

	"""
	Start the logger for the current process.


	This is based on the :exc:`logging` module.
	
	===============  ===========================================================
	Parameter  
	===============  ===========================================================
	*log_dir*  		 The directory that will contain the log file 
	*log_file*  	 The log file this logger will write to and manage. This will
					 exist in the *log_dir* directory.
	*log_level*   	 Log level to set the logger to 
	*service_type*   This string will be appended to the log filename so you 
					 can differentiate the log files by process type
	===============  ===========================================================

	"""

	print( "start_logger, log_dir:%s, log_file:%s, log_level:%s, service_type:%s" % (log_dir,log_file,log_level,service_type))

	global logger

	# set up some default logging settings for the root logger.
	#logging.basicConfig( level=logging.ERROR, format='%(asctime)s %(levelname)s %(message)s' )
	logging.basicConfig( level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s' )


	logger = logging.getLogger( "dmq_service" )

	if not os.path.exists( log_dir ):
		# try to create it
		os.mkdir( log_dir )

	log_handler = logging.handlers.TimedRotatingFileHandler( "%s/%s" % (log_dir, log_file ),
		when='midnight',
		backupCount=32,
		utc=True
	)  

	log_handler.setFormatter( logging.Formatter( '%(name)s %(asctime)s %(levelname)s:%(message)s' ) )                                                                      
	logger.addHandler( log_handler )         

	setLogLevel( log_level )

	log( "Setup logger, log_dir:%s, log_file:%s, log_level:%s" % (log_dir,log_file,log_level), 'info')
#start_logger()

def set_proc_name(newname):
	"""
	Set the process name which is viewble from top or ps.

	===============  ===========================================================
	Parameter  
	===============  ===========================================================
	*newname*   	 The new name of the process.  
	===============  ===========================================================

	By default, a python process is usually named after the interpeter. Something
	like "python2.6" or just "python". If there is only one python process, there 
	isn't a problem. However, after two or more python processes exits it becomes 
	difficult to detemine which one is yours. So, using this function, to 
	organize python process. 

	*This is only known to work on Linux systems.*
	"""
	
	try:
		libc = cdll.LoadLibrary('libc.so.6')
		buff = create_string_buffer(len(newname)+1)
		buff.value = newname
		libc.prctl(15, byref(buff), 0, 0, 0)
	except Exception as e:
		log("Unable to set process name to %s, %s" %(newname, e), 'warning')


def get_proc_name():
	"""
	Get the process name from the kernel. 

	===============  ===========================================================
	Parameter  
	===============  ===========================================================
						None
	===============  ===========================================================

	*This is only known to work on Linux systems.*
	"""

	try:
		libc = cdll.LoadLibrary('libc.so.6')
		buff = create_string_buffer(128)
		# 16 == PR_GET_NAME from <linux/prctl.h>
		libc.prctl(16, byref(buff), 0, 0, 0)
		return buff.value
	except Exception as e:
		log("Unable to get process name %s" %(e), 'warning')

	return ""
